National Park Service
U.S. Department of the Interior
Natural Resource Stewardship and Science
Abstract
This report summarizes data quality evaluations of discrete data collected for the Mojave Desert Network Inventory and Monitoring Program (MOJN I&M) Desert Springs protocol from 2016 to 2022. This protocol is designed to monitor hydrological and ecological condition at 250 springs in Death Valley National Park (DEVA), Joshua Tree National Park (JOTR), Lake Mead National Recreation Area (LAKE), Mojave National Preserve (MOJA), and Grand Canyon-Parashant National Monument (PARA). Data collected include water quantity and water quality measurements as well as site condition information about dominant vegetation, invasive plants, disturbance, and wildlife evidence.The following background information is summarized from the Springs in the Mojave Desert Network—Surface water monitoring at desert springs: Protocol narrative version 1.0 (NPS/MOJN/NRR—2018/1718), available here: https://irma.nps.gov/DataStore/Reference/Profile/2254900. Refer to the protocol narrative for more detailed information.
Springs are water sources that form where groundwater reaches the land surface. They can range in size from seasonal seeps that go dry in the summer to perennial streams that flow all year long and support large wetland environments (Figure 1). Compared to the surrounding desert, spring and wetland environments in the Mojave and Great Basin regions support a greater abundance and diversity of plant and animal life. Large mammals, like desert bighorn sheep, depend on standing water to survive the heat of summer. Many birds depend on riparian habitat during their migratory seasons, and bats frequent open pools when foraging for insects. Some springs support rare or endemic species, including fish, amphibians, and aquatic invertebrates. Reliable water sources are scarce, so springs are often vital to the distribution and connectivity of wildlife habitat across the landscape.
Figure 1. Examples of springs in the Mojave Desert.
Springs are vulnerable to multiple stressors, including climate change and groundwater withdrawal. In the southwestern United States, increasing air temperatures and declining snowpacks have intensified drought and reduced aquifer recharge (Gonzalez et al. 2018). Springs fed by small, local aquifers are particularly vulnerable to drought. They may experience lower discharge or even go dry entirely. Springs fed by larger, regional aquifers are more resilient to recent climate change but may be vulnerable to groundwater withdrawal happening outside of their park. For large aquifers with slow recharge, it may take centuries for water levels to recover after pumping is discontinued (Bredehoeft and Durbin 2009). At all springs, higher air temperatures can lead to water loss through increases in evapotranspiration as well as changes in plant communities and wildlife use patterns.
Other stressors include surface water diversions, livestock disturbance, recreation, and invasive species. Active and historical diversions, such as pipes and troughs, are widespread at springs within the network and may alter or eliminate downstream riparian habitat. Grazing and trampling by livestock, such as cattle, feral donkeys (burro), and feral horses, can also negatively affect riparian vegetation and habitat. Threats from improper recreation include social trails, fire pits, bank degradation, and failure to dispose of garbage and human waste. Invasive trees like salt cedar and palms often outcompete native plants for limited water and nutrients, and invasive grasses are shifting fire regimes across the landscape. Invasive animals, including amphibians, fish, arthropods, and molluscs, can put pressure on native species through predation, hybridization, or competition for resources.
The Mojave Desert Network Inventory and Monitoring Program (MOJN I&M) monitors 248 springs across Death Valley National Park (DEVA), Joshua Tree National Park (JOTR), Lake Mead National Recreation Area (LAKE), Mojave National Preserve (MOJA), and Grand Canyon-Parashant National Monument (PARA) as part of the Desert Springs protocol (Figure 2). Springs were selected at each park using a Generalized Random Tessellation Stratified (GRTS) spatially-balanced random sample.
A subset of 60 springs are monitored annually and are equipped with data-logging sensors to provide continuous records of surface water presence. There are 20 annual springs in DEVA and 10 annual springs in each of the other four parks. The remaining 188 springs are monitored on a 3-year rotation. There are 60 3-year springs in DEVA, 35 in MOJA, 35 in PARA, 33 in LAKE, and 25 in JOTR. Approximately 120 springs are monitored each field season.
Figure 2. Map of desert springs monitoring locations. Blue circles indicate springs monitored every year. Red circles indicate springs monitored every three years. Small yellow circles indicate springs that were inventoried but not typically monitored.
Given the ecological importance of springs and the threats that they face, the Desert Springs protocol was developed to address the following monitoring questions:
The protocol investigates these monitoring questions by collecting long-term data for the following quantitative measurable objectives:
In addition to these measurable objectives, the protocol also collects qualitative site condition information, including:
Because MOJN I&M field crews are often the only NPS field crews visiting many of these springs regularly, this site condition information can provide park managers with useful information about springs that would not be collected otherwise.
Field methods used are described in Springs in the Mojave Desert Network—Surface water monitoring at desert springs: Standard operating procedures version 1.0, available here: https://irma.nps.gov/DataStore/Reference/Profile/2256063. Specific methods include SOP 4: Spring Acceptance and Classification, SOP 5: Water Availability: Flow Condition, SOP 6: Water Availability: Data-Logging Sensors, SOP 7: Water Quality, SOP 8: Site Condition: Spring Vegetation, SOP 9: Site Condition: Invasive Plants, SOP 10: Site Condition: Disturbance, and SOP 11: Site Condition: Repeat Photographs. Table 1 summarizes all measurements that are collected for the protocol.
Table 1. Monitoring data collected for the Desert Springs protocol.
Data were evaluated using a collection of QC checks that are part of the MOJN I&M Desert Springs R package. These evaluations are summarized in Section 4 of this document. Where unresolvable data quality issues exist, the data have been assigned a flag to indicate the level of concern and further described by a flag note. These flags include Information (not expected to impact the validity of the data), Warning (care should be taken when including the data in analyses), and Critical (serious concerns about the quality of the data, and they should not be used in analyses).
All of the code used in the preparation of this data package is available in the MOJN I&M Desert Springs R Package [INSERT LINK].
The published product is one data package containing multiple CSV data files:
Twenty CSV data files contain raw values suitable for use with the MOJN I&M Desert Springs R package (Table 2).
A data dictionary for all of the tables and fields in the published CSV files is provided in XML format with this data package.
Table 2. File names and descriptions of published CSVs accompanying this data release report.
The data in the data package described above have been reviewed by staff in the NPS Inventory and Monitoring Division to ensure accuracy, completeness, and consistency with documented data quality standards, as well as for usability and reproducibility. For additional information on data quality standards for this protocol, refer to Data Quality Standards for Springs in the Mojave Desert Network–Surface Water Monitoring at Desert Springs (NPS/MOJN/NRR—2018/1819), available here: https://irma.nps.gov/DataStore/Reference/Profile/2257548.
This table provides the number and percentage of springs monitored at each park for each field season. Large disruptions to the field season occurred in WY2019 with the 35-day lapse in federal appropriations and in WY2020 and WY2021 with travel restrictions due to the COVID-19 pandemic.
Table 3. Number and percentage of springs monitored at each park and field season.
This stacked bar plot shows the percentage of springs monitored at each park for each field season. Large disruptions to the field season occurred in WY2019 with the 35-day lapse in federal appropriations and in WY2020 and WY2021 with travel restrictions due to the COVID-19 pandemic.
Figure 3. Annual and 3-yr spring sampled and not sampled at each park for each field season.
This table lists springs that were not sampled during a field season or visit when they were intended to be monitored.
Table 4. Springs that were not samped during a field season.
This table provides the date (month and day) that each spring was visited during each field season. Springs should be visited at approximately the same time of year during each field season, ideally within a few weeks, in order to minimize seasonal effects on the data.
Table 5. Date (month and day) that each spring was visited during each field season.
This table provides the site codes of springs that were visited on each date during each field season.
Table 6. Springs that were visited on each date (month and day) during each field season.
These timelines show the date (month and day) that each spring was visited during each field season. They also show the median visit date across all field seasons at each spring. Springs should be visited at approximately the same time of year during each field season, ideally within a few weeks, in order to minimize seasonal effects on the data.
Figure 4. Timeline of annual and 3-yr spring visits in DEVA.
Figure 5. Timeline of annual and 3-yr spring visits in JOTR.
Figure 6. Timeline of annual and 3-yr spring visits in LAKE.
Figure 7. Timeline of annual and 3-yr spring visits in MOJA.
Figure 8. Timeline of annual and 3-yr spring visits in PARA.
This table provides a list of springs that were visited multiple times during a field season. There should only be one primary visit per field season. Supplemental visits involve collecting specific data to supplement the data collected during the primary visit. Supplemental visits typically occur when a sensor is inadvertently forgotten during the primary visit and the spring is revisited later in the field season for sensor deployment. Replicate visits involve collecting a full set of data in addition to the data collected during the primary visit. Replicate visits may occur during training or when calibrating or comparing field crews.
Table 7. Springs visited more than one time per field season.
This table provides a list of springs that have been categorized differently (e.g., rheocrene vs hillslope) during different visits. Discrepancies typically occur when a spring is dry, and it is difficult to determine the spring type, or when a spring exhibits multiple spring types along its reach.
Table 8. Springs that have been assigned different spring types during different visits.
This table lists site visits that have any data labeled as “Raw” or “Provisional.” These data need to be reviewed and moved to “Accepted” status before publication of the dataset.
Table 9. Records with data still labeled as Raw or Provisional.
The above records need to be reviewed and accepted before publication.
Water quantity is the master variable in spring environments. The amount, timing, and duration of discharge control the character and extent of different aquatic habitats, the abundance of wetland plants that can be supported, and the ability of wildlife to access water for drinking.
This table provides spring flow condition and either estimated discharge (discharge class) or volumetric discharge for each visit.
Table 10. Spring flow condition, springbrook length, and discharge.
This table lists visits where the spring was recorded as dry, but either discharge or springbrook length were recorded as greater than 0.
Table 11. Dry springs with recorded discharge or springbrook length.
This table lists visits where the spring was not recorded as dry and discharge was recorded as 0 or where the spring was not recorded as dry or wet soil only and springbrook length was recorded as 0. The former situation can arise when wet soil is believed to result from recent rainfall or snowmelt as opposed to groundwater discharge. The latter condition can arise when there is water dripping from a pipe that is not enough to saturate the soil below.
Table 12. Non-dry springs without recorded discharge or springbrook length.
This table lists visits where estimated discharge (discharge class) or volumetric discharge were not recorded.
Table 13. Spring visits with missing discharge data.
This table lists visits where the volumetric method was used, but container volume, percent of flow, or fill time data were not recorded. Missing any one of these data types makes it impossible to calculate discharge.
Table 14. Volumetric discharge measurements with missing volumetric data.
This table lists visits where the volumetric method was used, but there are fewer than 5 fill times. Typically, at least 5 fill times are necessary to reduce the effect of outliers on determining the median fill time.
Table 15. Volumetric discharge measurements with fewer than five fill times.
This table lists visits where the volumetric method was used, but the median fill time was less than 5 seconds. Typically, fill times should be greater than 5 seconds to provide sufficient accuracy and precision.
Table 16. Volumetric discharge measurements with median fill time less than five seconds.
This table lists visits where continuous surface water length is greater than discontinuous surface water length. This results from error during data entry.
Table 17. Continuous surface water length greater than discontinuous surface water length.
This table summarizes flow categories for the continuous portion of springbrooks.
Table 18. Flow category summaries for the continuous portion of springbrooks at each park.
This table summarizes flow categories for the discontinuous portion of springbrooks, where springbrook lengths are discontinuous, and the continuous portion of springbrooks, where springbrook lengths are continuous.
Table 19. Flow category summaries for the discontinuous portion of springbrooks at each park.
This stacked bar plot summarizes flow categories for annual springs, using the discontinuous portion of springbrooks where applicable. Flow categories include dry, wet soil only, and three classes of springbrook length (m) when surface water is present.
Figure 9. Stacked bar plot of flow categories at annual springs for each park.
This stacked bar plot summarizes flow categories for 3-year springs, using the discontinuous portion of springbrooks where applicable. Flow categories include dry, wet soil only, and three classes of springbrook length (m) when surface water is present.
Figure 10. Stacked bar plot of flow categories at 3-yr springs for each park.
This heatmap shows flow categories at each annual spring over all field seasons, using the discontinuous portion of springbrooks where applicable. Flow categories include dry, wet soil only, and three classes of springbrook length (m) when surface water is present.
Figure 11. Heatmap of flow categories at annual springs in DEVA.
Figure 12. Heatmap of flow categories at annual springs in JOTR.
Figure 13. Heatmap of flow categories at annual springs in LAKE.
Figure 14. Heatmap of flow categories at annual springs in MOJA.
Figure 15. Heatmap of flow categories at annual springs in PARA.
This heatmap shows flow categories at each 3-year spring over all field seasons, using the discontinuous portion of springbrooks where applicable. Flow categories include dry, wet soil only, and three classes of springbrook length (m) when surface water is present.
Figure 16. Heatmap of flow categories at 3-yr springs in DEVA.
Figure 17. Heatmap of flow categories at 3-yr springs in JOTR.
Figure 18. Heatmap of flow categories at 3-yr springs in LAKE.
Figure 19. Heatmap of flow categories at 3-yr springs in MOJA.
Figure 20. Heatmap of flow categories at 3-yr springs in PARA.
This map shows flow categories at annual and 3-year springs, using the discontinuous portion of springbrooks where applicable. If there is a field season slider at the top of the map, then data from a specific field season may be selected. If there is no field season slider, then data from the most recent field season are shown.
Figure 21. Map of flow categories at springs in each park.
Water quality includes four parameters: water temperature, specific conductance, pH, and dissolved oxygen. Water temperature influences many chemical and physical properties of water as well as the metabolic activity of aquatic organisms. Specific conductance is related to salinity and measures the concentration of dissolved ions in the water, which can help detect contamination or disturbance. pH affects the solubility and toxicity of chemicals and heavy metals in the water. Dissolved oxygen sustains aquatic organisms that breathe aerobically, including crustaceans, mollusks, insects, amphibians, and fish.
These are water quality values that fall above or below the ranges that we typically see in spring systems. These data are not necessarily incorrect, but they are outliers that should be evaluated using data quality flags and field notes. Wildly impossible values may be the result of instrument malfunction, improper calibration, or typos during data entry. The following records are included in the list below: temperature values greater than 30 C, pH values greater than 10 and less than 6, specific conductance values greater than 20000 uS/cm, dissolved oxygen percent values greater than 110% or less than 2%, and dissolved oxygen concentration values greater than 12 mg/L.
Table 20. Water quality values that fall outside of expected ranges.
These are water quality values that have data quality flags. I = Information: These data do not have any suspected problems, but there may be information regarding the equipment or conditions in which they were collected that could inform their interpretation. W = Warning: These data are suspected to have problems and should only be used after careful assessment of instrument and environmental factors. C = Critical: These data are suspected to have serious problems and are likely unusable.
Table 21. Water quality values that have data quality flags.
This table lists visits where dissolved oxygen percent was not calibrated to local dissolved oxygen. When calibrating to local dissolved oxygen, the calibration value is 100% regardless of the barometric pressure at the time of calibration. The 100% calibration value for this convention reflects the fact that the calibration environment is at 100% oxygen pressure for that specific location.
Table 22. Calibration events where dissolved oxygen was not calibrated to local dissolved oxygen.
This table lists visits where the specific conductance standard used during calibration was much lower than the in-situ reading of specific conductance at the spring. Ideally, specific conductance standards of 10,000 uS/cm or even 50,000 uS/cm should be used at springs with consistently higher specific conductance readings.
Table 23. Calibration events where specific conductance was calibrated to a standard much lower than the in-situ reading at the spring.
This table summarizes the median and quartile values for each water quality parameter for each park and field season during the reporting period. Both annual and 3-year springs are included. Data flagged as “Warning” or “Critical” are not included.
Table 24. Water quality median and quartile values for each park and field season.
These box plots show the median and quartile values for water temperature (C) for each park and 3-year cycle during the reporting period. Both annual and 3-year springs are included in the 3-year cycles. Data flagged as “Warning” or “Critical” are not included.
Figure 22. Box plots of water temperature quartiles for each park and 3-year cycle.
These box plots show the median and quartile values for specific conductance (uS/cm) for each park and 3-year cycle during the reporting period. Both annual and 3-year springs are included in the 3-year cycles. Data flagged as “Warning” or “Critical” are not included.
Figure 23. Box plots of specific conductance quartiles for each park and 3-year cycle.
These box plots show the median and quartile values for pH for each park and 3-year cycle during the reporting period. Both annual and 3-year springs are included in the 3-year cycles. Data flagged as “Warning” or “Critical” are not included.
Figure 24. Box plots of pH quartiles for each park and 3-year cycle.
These box plots show the median and quartile values for dissolved oxygen concentration (mg/L) for each park and 3-year cycle during the reporting period. Both annual and 3-year springs are included in the 3-year cycles. Data flagged as “Warning” or “Critical” are not included.
Figure 25. Box plots of dissolved oxygen concentration quartiles for each park and 3-year cycle.
This map shows water temperature (C) at annual and 3-year springs where water was present. If there is a field season slider at the top of the map, then data from a specific field season may be selected. If there is no field season slider, then data from the most recent field season are shown.
Figure 26. Map of water temperature readings at springs in each park.
This map shows specific conductance (uS/cm) at annual and 3-year springs where water was present. If there is a field season slider at the top of the map, then data from a specific field season may be selected. If there is no field season slider, then data from the most recent field season are shown.
Figure 27. Map of specific conductance readings at springs in each park.
This map shows pH at annual and 3-year springs where water was present. If there is a field season slider at the top of the map, then data from a specific field season may be selected. If there is no field season slider, then data from the most recent field season are shown.
Figure 28. Map of pH readings at springs in each park.
This map shows dissolved oxygen concentration (mg/L) at annual and 3-year springs where water was present. If there is a field season slider at the top of the map, then data from a specific field season may be selected. If there is no field season slider, then data from the most recent field season are shown.
Figure 29. Map of dissolved oxygen concentration readings at springs in each park.
This table lists visits where vegetation was recorded as present, but no lifeforms were documented.
Table 25. Vegetation present but no lifeforms documented.
This table lists visits where vegetation was not recorded as present, but lifeforms were documented.
Table 26. Vegetation not present but one or more lifeforms documented.
This table lists visits where one or more lifeforms are missing a rank.
Table 27. Vegetation lifeform documented but missing rank.
This table lists visits where multiple life forms have the same rank, and rank gaps have not been properly entered.
Table 28. Spring visits where vegetation lifeform ranks have been incorrectly documented.
This table counts the number of springs where each lifeform was observed in each park and field season.
Table 29. Vegetation lifeform observations for each park and field season.
This table lists visits where targeted invasive plants were observed. Targeted invasive plants include saltcedar (Tamarix ramosissima), California fan palm (Washingtonia filifera), date palm (Phoenix dactylifera), and fountain grass (Pennisetum setaceum). California fans palms are native to Joshua Tree National Park, so any observations there are not included in this table.
Table 30. Targeted invasive plants observed at springs.
This map shows observations of targeted invasive plant species. If there is a field season slider at the top of the map, then data from a specific field season may be selected. If there is no field season slider, then data from the most recent field season are shown.
Figure 30. Map of targeted invasive plants observed at springs in each park.
This table lists visits where overall disturbance was less than any other disturbance category. This indicates error during data entry.
Table 31. Overall disturbance less than any other disturbance category.
This table lists visits were flow modification exists, but no human use disturbance was recorded at the spring.
Table 32. Flow modification present, but no human use disturbance recorded.
This table provides a list of springs where different flow modification types have been recorded during different visits. This may happen if a flow modification type is overlooked in one or more field seasons, a spring source shifts, or a different area around the spring source is searched during a visit.
Table 33. Springs that have been assigned different flow modification types during different visits.
This table lists springs where active or inactive (historical) flow modification was observed in each field season.
Table 34. Springs where active or inactive (historical) flow modification have been observed.
This table lists the number and percentage of springs where active, inactive (historical), or no flow modification have been observed. In situations where there are discrepancies in flow modification observations at a spring across different field seasons, the highest level of modification has been counted.
Table 35. Number and percentage of springs with flow modification in each park.
This bar plot shows the percentage of springs in each park where active, inactive (historical), or no flow modification have been observed. In situations where there are discrepancies in flow modification observations at a spring across different field seasons, the highest level of modification has been counted.
Figure 31. Stacked bar plot of flow modification status at springs in each park.
This table lists the number and percentage of springs where human use or livestock disturbance have been observed. Disturbance at a spring is counted if it has been observed at least once during the reporting period.
Table 36. Number and percentage of springs with human use or livestock disturbance in each park.
This table lists visits where human use disturbance was recorded at a spring.
Table 37. Human use disturbance observed at springs.
This bar plot shows the percentage of springs in each park where human use disturbance was observed.
Figure 32. Bar plots of human use disturbance observed at springs in each park.
This map shows where human use disturbance was observed. If there is a field season slider at the top of the map, then data from a specific field season may be selected. If there is no field season slider, then data from the most recent field season are shown.
Figure 33. Map of human use disturbance observed at springs in each park.
This table lists visits where livestock disturbance was recorded at a spring.
Table 38. Livestock disturbance observed at springs.
This bar plot shows the percentage of springs in each park where livestock disturbance was observed.
Figure 34. Bar plots of livestock disturbance observed at springs in each park.
This map shows where livestock disturbance was observed. If there is a field season slider at the top of the map, then data from a specific field season may be selected. If there is no field season slider, then data from the most recent field season are shown.
Figure 35. Map of livestock disturbance observed at springs in each park.
This table lists visits where wildlife was observed, but no wildlife type was specified.
Table 39. Wildlife was observed, but no wildlife type was specified.
This table lists visits where wildlife type was specified, but no evidence type was recorded.
Table 40. Wildlife type was specified, but no evidence type was recorded.
This table lists visits were evidence of ungulate (sheep or deer) activity was observed at a spring. Evidence can include direct observation, tracks, or scat.
Table 41. Ungulate activity observed at springs.
This map shows where evidence of ungulate (sheep or deer) activity was observed. Evidence can include direction observation, tracks, or scat. If there is a field season slider at the top of the map, then data from a specific field season may be selected. If there is no field season slider, then data from the most recent field season are shown.
Figure 36. Map of ungulate activity observed at springs in each park.
A MOJN Desert Springs R Package that is designed to work with the datasets in their published format is available on GitHub. This package was used to implement the quality checks that are included in this report and to generate the three calculated datasets that are included in this data package.
The authors would like to acknowledge Geoff Moret, who developed the Desert Springs protocol. We would also like to thank Lise Grace for providing review and editing assistance on this data release report.
Bailard J.L., Moret G.J., Lehman M., Hupp N.R., Tallent N.G., Calvert A.W. 2018. Springs in the Mojave Desert Network—Surface water monitoring at desert springs: Standard operating procedures version 1.0. National Park Service. Fort Collins, Colorado. Available at: https://irma.nps.gov/DataStore/Reference/Profile/2256063
Bredehoeft, J. and T. Durbin. 2009. Ground water development – the time to full capture problem. Ground Water: Vol. 47, Iss. 4, pp. 506–514. Available at: http://water.nv.gov/Hearings/past/Spring%20-%20Cave%20-%20Dry%20Lake%20and%20Delamar%20Valleys%202011/Exhibits/GBWN%20Exhibits/GBWN_Exh_012%20Bredehoeft%20Durbin_Ground%20Water%202009.pdf.
Gonzalez, P., G.M. Garfin, D.D. Breshears, K.M. Brooks, H.E. Brown, E.H. Elias, A. Gunasekara, N. Huntly, J.K. Maldonado, N.J. Mantua, H.G. Margolis, S. McAfee, B.R. Middleton, and B.H. Udall. 2018. Southwest. In Impacts, Risks, and Adaptation in the United States: Fourth National Climate Assessment, Volume II [Reidmiller, D.R., C.W. Avery, D.R. Easterling, K.E. Kunkel, K.L.M. Lewis, T.K. Maycock, and B.C. Stewart (eds.)]. U.S. Global Change Research Program, Washington, DC: pp. 1101–1184. doi: 10.7930/NCA4.2018.CH25. Available at: https://nca2018.globalchange.gov/chapter/25/
Moret G.J., Bailard J.L., Lehman M., Hupp N.R., Tallent N.G., Calvert A.W. 2018. Springs in the Mojave Desert Network—Surface water monitoring at desert springs: Protocol narrative version 1.0. Natural Resource Report. NPS/MOJN/NRR—2018/1718. National Park Service. Fort Collins, Colorado. Available at: https://irma.nps.gov/DataStore/Reference/Profile/2254900
# This setup code loads both reproducible reporting packages
# (delete those not needed) and packages for the actual project.
# Note that it also generates the start of a BibTex literature cited
# including the citations for R and all used packages
# reproducible reporting packages
RRpackages <- c('markdown', # links to Sundown rendering library
'rmarkdown', # newer rendering via pandoc
'pander', # alternative renderer for markdown, plus better tables than just knitr
'knitr',
"dataMaid", # for makeCodebooks
"R.rsp", # dynamic generation of scientific reports
"kimisc", #
"papeR", # stat tables
"texreg", # formatting regression results for LaTeX or html
"rmdHelpers", # misc from Mark Peterson thisFileName() thisFile_knit()
'yaml', # format data into markdown
'rmdformats', # templates including automatic ToC, also use_bookdown()
'htmltools', #
"bibtex",
"RefManageR", # BibTeX reference manager
"knitcitations",# For working with file paths
"here" # nice HTML widget tables
)
inst <- RRpackages %in% installed.packages()
if (length(RRpackages[!inst]) > 0) {
install.packages(RRpackages[!inst], dep = TRUE, repos = "http://cran.rstudio.com/") # "https://cloud.r-project.org"
}
lapply(RRpackages, library, character.only = TRUE)
# Now repeat for packages used in the analyses
pkgList <- c("devtools", # tends to be needed/useful
"RODBC", # for connection to a database.
"EML", # for data package creation and validation
"kableExtra", # added features for table formatting.
"english", # converts numbers into english. Good for all that English stuff.
"remotes", # for install_github()
"tidyverse", # useful
"formatR",
"magrittr",
"leaflet",
"plotly",
"svglite",
"scales",
"snakecase",
"reactable",
"slickR",
"gridExtra",
"glue",
"tidytext",
"DT")
inst <- pkgList %in% installed.packages()
if (length(pkgList[!inst]) > 0) {
install.packages(pkgList[!inst], dep = TRUE,
repos = "http://cran.rstudio.com/") # "https://cloud.r-project.org"
}
lapply(pkgList, library, character.only = TRUE, quietly = TRUE)
options(download.file.method = "wininet")
if (! "EMLassemblyline" %in% installed.packages()) remotes::install_github("EDIorg/EMLassemblyline")
if (! "desertsprings" %in% installed.packages()) remotes::install_github("nationalparkservice/mojn-ds-rpackage")
require("EMLassemblyline")
require("desertsprings")
# create stub of citations for packages
pkgBibTex <- lapply(c("base", pkgList, RRpackages), citation)
# pkgBibTex <- do.call()
knitr::opts_chunk$set(
root.dir = here::here(),
echo = FALSE,
comment = " ",
dev = "svg",
fig.path = here::here("figures"),
tidy.opts = list(width.cutoff = 60),
tidy = TRUE
)
# if ggplot, update theme to default to centered titles
if ("ggplot2" %in% .packages()) {
theme_update(plot.title = element_text(hjust = 0.5))
}
knitr::opts_chunk$set(fig.width=8)
LoadDesertSprings()
# Convert start and end water years assigned in the params to a year range that can be applied to functions through the field.season parameter
wy <- as.numeric(params$wateryearStart)
end <- as.numeric(params$wateryearEnd)
years <- tibble::tibble(wy) %>%
tibble::add_row(wy = end) %>%
tidyr::complete(wy = tidyr::full_seq(wy, 1)) %>%
unique() %>%
dplyr::mutate(wy = as.character(wy))
year.range <- paste0(years$wy)
# Function to adjust position of axis and legend labels in plotly objects
layout_ggplotly <- function(gg, x = -0.1, y = -0.05, x_legend=1.05, y_legend=0.95, mar=list(l=50, r=150)){
# The 1 and 2 goes into the list that contains the options for the x and y axis labels respectively
gg[['x']][['layout']][['annotations']][[1]][['y']] <- x
gg[['x']][['layout']][['annotations']][[2]][['x']] <- y
# gg[['x']][['layout']][['annotations']][[0]][['x']] <- x_legend # the legend title was the 11-th list element in my case!
gg[['x']][['layout']][['legend']][['y']] <- y_legend
gg[['x']][['layout']][['legend']][['x']] <- x_legend
gg %>% layout(margin = mar)
}
#Determine the output format of the document
outputFormat = opts_knit$get("rmarkdown.pandoc.to")
#Figure and Table Caption Numbering, for HTML do it manually
capTabNo = 1; capFigNo = 1;
#Function to add the Table Number
capTab = function(x){
if(outputFormat == 'html'){
x = paste0("<B>Table ", capTabNo, ". ", "</B>", x)
capTabNo <<- capTabNo + 1
}; x
}
#Function to add the Figure Number
capFig = function(x){
if(outputFormat == 'html'){
x = paste0("<B>Figure ", capFigNo, ". ", "</B>", x)
capFigNo <<- capFigNo + 1
}; x
}
# Write YAML parameters to file for consistent reuse across report and data packages
save(params,file=here::here("data", "temp", "reportParameters.RData"))
if (params$dataSource == "database") {
conn <- tryCatch(OpenDatabaseConnection(),
error = {conn <- NA})
} else {
conn <- NA
}
raw_data_path <- here::here("data", "raw")
source(here::here("dataPackages", "DataPackageTemplate", "generate-metadata.R"))
# Load datasets for use
if (file.exists(file=here::here("data", "temp", "projectMetadata.RData"))) {
load(file=here::here("data", "temp", "projectMetadata.RData"))
} else{
projectMetadata<-list()
}
dat <- tibble::tibble(filepath = glue::as_glue(c(here::here("figures", "MOJA_P_BLA0014.JPG"),
here::here("figures", "JOTR_P_QUE0109.JPG"),
here::here("figures", "LAKE_P_SAL0019.JPG"),
here::here("figures", "PARA_P_DEA0145.JPG"),
here::here("figures", "MOJA_P_SIL0180.JPG"),
here::here("figures", "DEVA_P_COR0991.JPG"),
here::here("figures", "LAKE_P_GRA0058.JPG"),
here::here("figures", "DEVA_P_CUR0123.JPG"),
here::here("figures", "PARA_P_RAT0212.JPG"),
here::here("figures", "DEVA_P_GNO0081.JPG"),
here::here("figures", "DEVA_P_COT0794.JPG"),
here::here("figures", "JOTR_P_COT0294.JPG"))))
alt_text <- c("Small, muddy puddle emerges from hillside, with cattle activity in the spring. There are some posts and other old remains of an exclosure fence around the source.",
"Small pool is situated in sand and bedrock at the bottom of a bouldery canyon.",
"Hot spring flows over a waterfall in a narrow canyon and is dammed by sandbags at the bottom to form a bathing pool.",
"Shallow, broad pond is situated in a grassy depression with pine trees in the background.",
"Shallow springbrook emerges from a qanat, with active pipe diversion and cattle activity in the spring.",
"Small pool supporting goldenrods emerges from a very steep hillside with little other vegetation around.",
"High discharge spring flows over a waterfall into a large, deep pool in a narrow canyon. The canyon is full of lush riparian vegetation, including cattails, monkeyflowers, grapevines, willows, and ferns.",
"Small, shallow pool emerges in the middle of sparse desert shrubland and flows for a few meters down a gradual slope.",
"Water seeps out of contacts between bedrock layers, with active pipe diversion of the seepage.",
"Long, narrow springbrook winds through a crusty salt flat devoid of vegetation.",
"Shallow springbrook is covered by aquatic plants in the shade of large cottonwood trees and other woody vegetation.",
"Dry spring is situated in a sandy wash below cluster of fan palms in a bouldery canyon.")
cap <- c("Black Bird Mine Spring, Mojave National Preserve",
"Queen Mountain Spring, Joshua Tree National Park",
"Salt Cedar Hot Spring, Lake Mead National Recreation Area",
"Death Valley Pond, Parashant National Monument",
"Silver Lead Qanat, Mojave National Preserve",
"Corkscrew Spring, Death Valley National Park",
"Grapevine Spring, Lake Mead National Recreation Area",
"Currie Wells, Death Valley National Park",
"Rattlesnake Spring, Parashant National Monument",
"Gnome Spring, Death Valley National Park",
"Cottonwood Spring, Death Valley National Park",
"Cottonwood Palm Spring, Joshua Tree National Park")
imgs_alt <- mapply(function(x, txt){
htmltools::tags$img(src = x, title = txt)
}, x = dat$filepath, txt = alt_text, SIMPLIFY = FALSE)
cP1 <- htmlwidgets::JS("function(slick,index) {
return '<a>'+(index+1)+'</a>';
}")
opts_dot_number <- slickR::settings(
focusOnSelect = TRUE,
dots = TRUE,
customPaging = cP1
)
slick_dots <- slickR::slickR(
obj = imgs_alt,
height = 400,
width = "60%"
)
slick_cap_synch <- slickR(obj = cap, slideType = "p") + settings(arrows = FALSE)
slick_dots %synch% slick_cap_synch + opts_dot_number
locationmap <- LocationMap()
locationmap
type <- c("Quantitative", "Quantitative", "Quantitative", "Qualitative", "Qualitative", "Qualitative", "Qualitative", "Qualitative")
msr <- c("Water Availability (Discrete)", "Water Availability (Continuous)", "Water Quality", "Dominant Vegetation", "Invasive Plants", "Wildlife Evidence", "Disturbance", "Repeat Photographs")
dscr <- c("Flow condition (presence or absence of surface water), discharge (flow rate of surface water), surface water dimensions (length and width of surface water)", "Record of wet / dry cycle (data-logging sensors)", "Core parameters (temperature, pH, specific conductance, and dissolved oxygen)", "Ranking of vegetation life forms within spring area", "List of invasive plants found within spring area", "List and description of wildlife evidence within spring area", "Index of natural and anthropogenic disturbances within spring area", "Visual documentation of spring source, upstream, and downstream")
tbl <- tibble::tibble(type, msr, dscr) %>%
dplyr::rename(MeasurementType = type,
Measurement = msr,
Description = dscr)
tbl %>%
reactable::reactable(
compact = TRUE,
striped = TRUE,
bordered = TRUE,
highlight = TRUE,
resizable = TRUE,
columns = list(
MeasurementType = reactable::colDef(minWidth = 130,
name = "Measurement Type"),
Measurement = reactable::colDef(minWidth = 180),
Description = reactable::colDef(minWidth = 300)))
FileName <- c("CalibrationDO", "CalibrationpH", "CalibrationSpCond", "DischargeEstimated", "DischargeFlowCondition", "DischargeVolumetric", "Disturbance", "DisturbanceFlowModification", "Invasives", "Riparian", "SensorRetrievalAttempts", "SensorsCurrentlyDeployed", "Site", "Visit", "VisitActivity", "WaterQualityDO", "WaterQualitypH", "WaterQualitySpCond", "WaterQualityTemperature", "Wildlife")
Description <- c("Dissolved oxgyen calibration records", "pH calibration records", "Specific conductance calibration records", "Visually estimated discharge categories", "Springbrook lengths, widths, and flow condition categories", "Volumetrically collected discharge measurements", "Natural and anthropogenic disturbance presence, cover classes, and descriptions", "Presence and type of surface flow modifications", "Invasive vegetation species observations", "Vegetation life form category presence, rank, and dominant species", "Sensor recovery and download results and problems", "Serial numbers of currently deployed sensors", "Locations of spring sites in this dataset", "Sample frames, visit types, and monitoring status of spring sites", "Summary of types of data collected during site visits", "Dissolved oxygen measurements in springs", "pH measurements in springs", "Specific conductance measurements in springs", "Water temperature measurements in springs", "Wildlife use evidence types and descriptions")
tbl <- data.frame(FileName, Description)
tbl %>%
reactable::reactable(
columns = list(FileName = reactable::colDef(name = "Filename",
minWidth = 140),
Description = reactable::colDef(minWidth = 320)),
pagination = FALSE,
compact = TRUE,
striped = TRUE,
bordered = TRUE,
highlight = TRUE,
resizable = TRUE)
completeness <- qcCompleteness(field.season = year.range)
completeness %<>%
dplyr::mutate(Percent = round(Percent, 1)) %>%
dplyr::filter(MonitoringStatus == "Sampled")
completeness %>%
reactable::reactable(sortable = TRUE,
filterable = TRUE,
compact = TRUE,
striped = TRUE,
bordered = TRUE,
highlight = TRUE,
resizable = TRUE,
defaultColDef = reactable::colDef(
header = function(value) snakecase::to_title_case(value)))
completeness.plot <- qcCompletenessPlot(field.season = year.range)
if (params$isAccessible == "yes") {
completeness.plot
} else {
ggplotly(completeness.plot) %>%
layout(
legend = list(
orientation = "h",
y = -0.2,
title = list(text = "Sample Status")
)
)
}
notsampled <- qcNotSampled(field.season = year.range)
notsampled %>%
reactable::reactable(sortable = TRUE,
filterable = TRUE,
compact = TRUE,
striped = TRUE,
bordered = TRUE,
highlight = TRUE,
resizable = TRUE,
defaultColDef = reactable::colDef(
header = function(value) snakecase::to_title_case(value)))
visitsbysite <- qcVisitsBySite(field.season = year.range)
visitsbysite %>%
reactable::reactable(sortable = TRUE,
filterable = TRUE,
compact = TRUE,
striped = TRUE,
bordered = TRUE,
highlight = TRUE,
resizable = TRUE,
columns = list(
VisitDates = reactable::colDef(
minWidth = 115),
SiteCode = reactable::colDef(
minWidth = 160),
SampleFrame = reactable::colDef(
minWidth = 150),
SiteName = reactable::colDef(
minWidth = 150)),
defaultColDef = reactable::colDef(
header = function(value) snakecase::to_title_case(value)))
visitsbydate <- qcVisitsByDate(field.season = year.range)
visitsbydate %>%
reactable::reactable(sortable = TRUE,
filterable = TRUE,
compact = TRUE,
striped = TRUE,
bordered = TRUE,
highlight = TRUE,
resizable = TRUE,
defaultColDef = reactable::colDef(
width = 160,
header = function(value) gsub("Y", "Y ", value)),
columns = list(
Date = reactable::colDef(
sticky = "left",
style = list(borderRight = "1px solid #eee"),
headerStyle = list(borderRight = "1px solid #eee"),
width = 100)))
visitdate.plots <- qcVisitDateTimelines(park = "DEVA", field.season = year.range)
if (params$isAccessible == "yes") {
visitdate.plots
} else {
p <- ggplotly(visitdate.plots, tooltip = c("text"))
for (i in 1:length(p$x$data)){
if (!is.null(p$x$data[[i]]$name)){
p$x$data[[i]]$name = gsub("\\(","",str_split(p$x$data[[i]]$name,",")[[1]][1])
}
}
p
}
visitdate.plots <- qcVisitDateTimelines(park = "JOTR", field.season = year.range)
if (params$isAccessible == "yes") {
visitdate.plots
} else {
p <- ggplotly(visitdate.plots, tooltip = c("text"))
for (i in 1:length(p$x$data)){
if (!is.null(p$x$data[[i]]$name)){
p$x$data[[i]]$name = gsub("\\(","",str_split(p$x$data[[i]]$name,",")[[1]][1])
}
}
p
}
visitdate.plots <- qcVisitDateTimelines(park = "LAKE", field.season = year.range)
if (params$isAccessible == "yes") {
visitdate.plots
} else {
p <- ggplotly(visitdate.plots, tooltip = c("text"))
for (i in 1:length(p$x$data)){
if (!is.null(p$x$data[[i]]$name)){
p$x$data[[i]]$name = gsub("\\(","",str_split(p$x$data[[i]]$name,",")[[1]][1])
}
}
p
}
visitdate.plots <- qcVisitDateTimelines(park = "MOJA", field.season = year.range)
if (params$isAccessible == "yes") {
visitdate.plots
} else {
p <- ggplotly(visitdate.plots, tooltip = c("text"))
for (i in 1:length(p$x$data)){
if (!is.null(p$x$data[[i]]$name)){
p$x$data[[i]]$name = gsub("\\(","",str_split(p$x$data[[i]]$name,",")[[1]][1])
}
}
p
}
visitdate.plots <- qcVisitDateTimelines(park = "PARA", field.season = year.range)
if (params$isAccessible == "yes") {
visitdate.plots
} else {
p <- ggplotly(visitdate.plots, tooltip = c("text"))
for (i in 1:length(p$x$data)){
if (!is.null(p$x$data[[i]]$name)){
p$x$data[[i]]$name = gsub("\\(","",str_split(p$x$data[[i]]$name,",")[[1]][1])
}
}
p
}
repeats <- qcRepeatVisits(field.season = year.range)
reactable::reactable(dplyr::select(repeats, -Notes),
defaultColDef = reactable::colDef(minWidth = 50,
header = function(value) snakecase::to_title_case(value)),
details = reactable::colDef(
name = "Notes",
details = function(index) {
note <- repeats$Notes[index]
if (!is.na(note)) {
return(note)
}
}
),
sortable = TRUE,
filterable = TRUE,
compact = TRUE,
striped = TRUE,
bordered = TRUE,
highlight = TRUE,
resizable = TRUE)
discrepancies <- qcSpringTypeDiscrepancies(field.season = year.range)
discrepancies %>%
reactable::reactable(sortable = TRUE,
filterable = TRUE,
compact = TRUE,
striped = TRUE,
bordered = TRUE,
highlight = TRUE,
resizable = TRUE,
defaultColDef = reactable::colDef(header = function(value) snakecase::to_title_case(value)))
dpl.check <- qcDPLCheck(field.season = year.range)
dpl.check %>%
dplyr::rename_with(~ gsub(".DPL", "", .x)) %>%
reactable::reactable(sortable = TRUE,
filterable = TRUE,
compact = TRUE,
striped = TRUE,
bordered = TRUE,
highlight = TRUE,
resizable = TRUE,
defaultColDef = reactable::colDef(header = function(value) if (value == "pH") {
value
} else {
snakecase::to_title_case(value)
}))
springdischarge <- SpringDischarge(field.season = year.range) %>%
dplyr::select(-Panel) %>%
tidyr::unite("Notes", c("DischargeNotes", "SpringbrookNotes"), remove = TRUE, na.rm = TRUE, sep = " ") %>%
dplyr::mutate(Notes = case_when(Notes == "" ~ NA_character_,
TRUE ~ Notes))
reactable::reactable(dplyr::select(springdischarge, -Notes),
details = reactable::colDef(
name = "Notes",
details = function(index) {
note <- springdischarge$Notes[index]
if (!is.na(note)) {
return(note)
}
}
),
sortable = TRUE,
filterable = TRUE,
compact = TRUE,
striped = TRUE,
bordered = TRUE,
highlight = TRUE,
resizable = TRUE,
defaultColDef = reactable::colDef(
header = function(value) snakecase::to_title_case(value)))
drynonzero <- qcSpringDryWater(field.season = year.range) %>%
dplyr::select(-Panel) %>%
tidyr::unite("Notes", c("DischargeNotes", "SpringbrookNotes"), remove = TRUE, na.rm = TRUE, sep = " ") %>%
dplyr::mutate(Notes = case_when(Notes == "" ~ NA_character_,
TRUE ~ Notes))
reactable::reactable(dplyr::select(drynonzero, -Notes),
defaultColDef = reactable::colDef(minWidth = 50,
header = function(value) snakecase::to_title_case(value)),
details = reactable::colDef(
name = "Notes",
details = function(index) {
note <- drynonzero$Notes[index]
if (!is.na(note)) {
return(note)
}
}
),
sortable = TRUE,
filterable = TRUE,
compact = TRUE,
striped = TRUE,
bordered = TRUE,
highlight = TRUE,
resizable = TRUE)
notdrynowater <- qcSpringNotDryNoWater(field.season = year.range) %>%
dplyr::select(-Panel) %>%
tidyr::unite("Notes", c("DischargeNotes", "SpringbrookNotes"), remove = TRUE, na.rm = TRUE, sep = " ") %>%
dplyr::mutate(Notes = case_when(Notes == "" ~ NA_character_,
TRUE ~ Notes))
reactable::reactable(dplyr::select(notdrynowater, -Notes),
defaultColDef = reactable::colDef(minWidth = 150,
header = function(value) snakecase::to_title_case(value)),
details = reactable::colDef(
name = "Notes",
details = function(index) {
note <- notdrynowater$Notes[index]
if (!is.na(note)) {
return(note)
}
}
),
sortable = TRUE,
filterable = TRUE,
compact = TRUE,
striped = TRUE,
bordered = TRUE,
highlight = TRUE,
resizable = TRUE)
dischargemissing <- qcDischargeMissing(field.season = year.range) %>%
dplyr::select(-Panel) %>%
tidyr::unite("Notes", c("DischargeNotes", "SpringbrookNotes"), remove = TRUE, na.rm = TRUE, sep = " ") %>%
dplyr::mutate(Notes = case_when(Notes == "" ~ NA_character_,
TRUE ~ Notes))
reactable::reactable(dplyr::select(dischargemissing, -Notes),
defaultColDef = reactable::colDef(minWidth = 50,
header = function(value) snakecase::to_title_case(value)),
details = reactable::colDef(
name = "Notes",
details = function(index) {
note <- dischargemissing$Notes[index]
if (!is.na(note)) {
return(note)
}
}
),
sortable = TRUE,
filterable = TRUE,
compact = TRUE,
striped = TRUE,
bordered = TRUE,
highlight = TRUE,
resizable = TRUE)
volumetricmissing <- qcVolumetricMissing(field.season = year.range)
volumetricmissing %>%
reactable::reactable(
sortable = TRUE,
filterable = TRUE,
compact = TRUE,
striped = TRUE,
bordered = TRUE,
highlight = TRUE,
resizable = TRUE,
defaultColDef = reactable::colDef(
header = function(value) snakecase::to_title_case(value)))
fillevents <- qcVolumetricFillEvents(field.season = year.range)
fillevents %>%
reactable::reactable(
sortable = TRUE,
filterable = TRUE,
compact = TRUE,
striped = TRUE,
bordered = TRUE,
highlight = TRUE,
resizable = TRUE,
defaultColDef = reactable::colDef(
header = function(value) snakecase::to_title_case(value)))
filltimes <- qcVolumetricTimes(field.season = year.range)
filltimes %>%
reactable::reactable(
sortable = TRUE,
filterable = TRUE,
compact = TRUE,
striped = TRUE,
bordered = TRUE,
highlight = TRUE,
resizable = TRUE,
defaultColDef = reactable::colDef(
header = function(value) snakecase::to_title_case(value)))
continuouslength <- qcContinuousLength(field.season = year.range)
continuouslength %>%
reactable::reactable(
sortable = TRUE,
filterable = TRUE,
compact = TRUE,
striped = TRUE,
bordered = TRUE,
highlight = TRUE,
resizable = TRUE,
defaultColDef = reactable::colDef(
header = function(value) snakecase::to_title_case(value)))
flowcatcon <- FlowCategoriesContinuous(field.season = year.range) %>%
dplyr::select(-Panel)
flowcatcon %>%
reactable::reactable(
sortable = TRUE,
filterable = TRUE,
compact = TRUE,
striped = TRUE,
bordered = TRUE,
highlight = TRUE,
resizable = TRUE,
defaultColDef = reactable::colDef(
header = function(value) snakecase::to_title_case(value)))
flowcatdiscon <- FlowCategoriesDiscontinuous(field.season = year.range) %>%
dplyr::select(-Panel)
flowcatdiscon %>%
reactable::reactable(
sortable = TRUE,
filterable = TRUE,
compact = TRUE,
striped = TRUE,
bordered = TRUE,
highlight = TRUE,
resizable = TRUE,
defaultColDef = reactable::colDef(
header = function(value) snakecase::to_title_case(value)))
flowcatannualplot <- FlowCategoriesAnnualPlot(field.season = year.range)
if (params$isAccessible == "yes") {
flowcatannualplot
} else {
ggplotly(flowcatannualplot) %>%
layout(
legend = list(
orientation = "h",
y = -0.2,
title = list(text = "Flow Category")
)
)
}
flowcat3yrplot <- FlowCategoriesThreeYearPlot(field.season = year.range)
if (params$isAccessible == "yes") {
flowcat3yrplot
} else {
ggplotly(flowcat3yrplot) %>%
layout(
legend = list(
orientation = "h",
y = -0.2,
title = list(text = "Flow Category")
)
)
}
flowcatannualheatmap <- FlowCategoriesAnnualHeatMap(park = "DEVA", field.season = year.range)
if (params$isAccessible == "yes") {
flowcatannualheatmap
} else {
ggplotly(flowcatannualheatmap, tooltip = "text") %>%
layout_ggplotly(x = 0, y = -0.05)
}
flowcatannualheatmap <- FlowCategoriesAnnualHeatMap(park = "JOTR", field.season = year.range)
if (params$isAccessible == "yes") {
flowcatannualheatmap
} else {
ggplotly(flowcatannualheatmap, tooltip = "text") %>%
layout_ggplotly(x = 0, y = -0.05)
}
flowcatannualheatmap <- FlowCategoriesAnnualHeatMap(park = "LAKE", field.season = year.range)
if (params$isAccessible == "yes") {
flowcatannualheatmap
} else {
ggplotly(flowcatannualheatmap, tooltip = "text") %>%
layout_ggplotly(x = 0, y = -0.05)
}
flowcatannualheatmap <- FlowCategoriesAnnualHeatMap(park = "MOJA", field.season = year.range)
if (params$isAccessible == "yes") {
flowcatannualheatmap
} else {
ggplotly(flowcatannualheatmap, tooltip = "text") %>%
layout_ggplotly(x = 0, y = -0.05)
}
flowcatannualheatmap <- FlowCategoriesAnnualHeatMap(park = "PARA", field.season = year.range)
if (params$isAccessible == "yes") {
flowcatannualheatmap
} else {
ggplotly(flowcatannualheatmap, tooltip = "text") %>%
layout_ggplotly(x = 0, y = -0.05)
}
flowcat3yrheatmap <- FlowCategoriesThreeYearHeatMap(park = "DEVA", field.season = year.range)
if (params$isAccessible == "yes") {
flowcat3yrheatmap
} else {
ggplotly(flowcat3yrheatmap, tooltip = "text") %>%
layout_ggplotly(x = 0, y = -0.05)
}
flowcat3yrheatmap <- FlowCategoriesThreeYearHeatMap(park = "JOTR", field.season = year.range)
if (params$isAccessible == "yes") {
flowcat3yrheatmap
} else {
ggplotly(flowcat3yrheatmap, tooltip = "text") %>%
layout_ggplotly(x = 0, y = -0.05)
}
flowcat3yrheatmap <- FlowCategoriesThreeYearHeatMap(park = "LAKE", field.season = year.range)
if (params$isAccessible == "yes") {
flowcat3yrheatmap
} else {
ggplotly(flowcat3yrheatmap, tooltip = "text") %>%
layout_ggplotly(x = 0, y = -0.05)
}
flowcat3yrheatmap <- FlowCategoriesThreeYearHeatMap(park = "MOJA", field.season = year.range)
if (params$isAccessible == "yes") {
flowcat3yrheatmap
} else {
ggplotly(flowcat3yrheatmap, tooltip = "text") %>%
layout_ggplotly(x = 0, y = -0.05)
}
flowcat3yrheatmap <- FlowCategoriesThreeYearHeatMap(park = "PARA", field.season = year.range)
if (params$isAccessible == "yes") {
flowcat3yrheatmap
} else {
ggplotly(flowcat3yrheatmap, tooltip = "text") %>%
layout_ggplotly(x = 0, y = -0.05)
}
# if (params$isAccessible == "yes") {
# flowcatmap_access <- FlowCategoriesMap(interactive = "no")
# flowcatmap_access
# } else {
flowcatmap_interactive <- FlowCategoriesMap(interactive = "yes", field.season = year.range)
flowcatmap_interactive
# }
wqsanity <- qcWqSanity(field.season = year.range)
wqsanity %>%
reactable::reactable(
sortable = TRUE,
filterable = TRUE,
compact = TRUE,
striped = TRUE,
bordered = TRUE,
highlight = TRUE,
resizable = TRUE,
defaultColDef = reactable::colDef(
header = function(value) snakecase::to_title_case(value)))
wqflags <- qcWqFlags(field.season = year.range)
reactable::reactable(dplyr::select(wqflags, -FlagNote),
defaultColDef = reactable::colDef(minWidth = 50,
header = function(value) snakecase::to_title_case(value)),
details = reactable::colDef(
name = "Notes",
details = function(index) {
note <- wqflags$FlagNote[index]
if (!is.na(note)) {
return(note)
}
}
),
sortable = TRUE,
filterable = TRUE,
compact = TRUE,
striped = TRUE,
bordered = TRUE,
highlight = TRUE,
resizable = TRUE,)
localdo <- qcLocalDOCheck(field.season = year.range)
localdo %>%
reactable::reactable(
sortable = TRUE,
filterable = TRUE,
compact = TRUE,
striped = TRUE,
bordered = TRUE,
highlight = TRUE,
resizable = TRUE,
defaultColDef = reactable::colDef(
header = function(value) snakecase::to_title_case(value)))
scstandard <- qcSpCondStandardCheck(field.season = year.range)
scstandard %>%
reactable::reactable(
sortable = TRUE,
filterable = TRUE,
compact = TRUE,
striped = TRUE,
bordered = TRUE,
highlight = TRUE,
resizable = TRUE,
defaultColDef = reactable::colDef(
header = function(value) snakecase::to_title_case(value)))
wqstats <- WqStats(field.season = year.range)
wqstats %<>% dplyr::filter(Park != "CAMO")
wqstats %>%
reactable::reactable(
sortable = TRUE,
filterable = TRUE,
compact = TRUE,
striped = TRUE,
bordered = TRUE,
highlight = TRUE,
resizable = TRUE,
defaultColDef = reactable::colDef(
header = function(value) snakecase::to_title_case(value)))
tempplot <- WqPlotTemp(field.season = year.range)
if (params$isAccessible == "yes") {
tempplot
} else {
ggplotly(tempplot) %>%
layout_ggplotly(x = -0.04, y = -0.01)
}
spcondplot <- WqPlotSpCond(field.season = year.range)
if (params$isAccessible == "yes") {
spcondplot
} else {
ggplotly(spcondplot) %>%
layout_ggplotly(x = -0.04, y = -0.01)
}
phplot <- WqPlotPH(field.season = year.range)
if (params$isAccessible == "yes") {
phplot
} else {
ggplotly(phplot) %>%
layout_ggplotly(x = -0.04, y = -0.01)
}
doplot <- WqPlotDOmgL(field.season = year.range)
if (params$isAccessible == "yes") {
doplot
} else {
ggplotly(doplot) %>%
layout_ggplotly(x = -0.04, y = -0.01)
}
tempmap <- WqMapTemp(field.season = year.range)
tempmap
spcondmap <- WqMapSpCond(field.season = year.range)
spcondmap
phmap <- WqMapPH(field.season = year.range)
phmap
domap <- WqMapDO(field.season = year.range)
domap
vegnolife <- qcVegPresentNoLifeforms(field.season = year.range)
vegnolife %>%
reactable::reactable(
sortable = TRUE,
filterable = TRUE,
compact = TRUE,
striped = TRUE,
bordered = TRUE,
highlight = TRUE,
resizable = TRUE,
defaultColDef = reactable::colDef(
header = function(value) snakecase::to_title_case(value)))
noveglife <- qcNoVegLifeformsPresent(field.season = year.range)
noveglife %>%
reactable::reactable(
sortable = TRUE,
filterable = TRUE,
compact = TRUE,
striped = TRUE,
bordered = TRUE,
highlight = TRUE,
resizable = TRUE,
defaultColDef = reactable::colDef(
header = function(value) snakecase::to_title_case(value)))
lifenorank <- qcLifeformPresentNoRank(field.season = year.range)
lifenorank %>%
reactable::reactable(
sortable = TRUE,
filterable = TRUE,
compact = TRUE,
striped = TRUE,
bordered = TRUE,
highlight = TRUE,
resizable = TRUE,
defaultColDef = reactable::colDef(
header = function(value) snakecase::to_title_case(value)))
rankcheck <- qcLifeformRankCheck(field.season = year.range)
rankcheck %>%
reactable::reactable(
sortable = TRUE,
filterable = TRUE,
compact = TRUE,
striped = TRUE,
bordered = TRUE,
highlight = TRUE,
resizable = TRUE,
defaultColDef = reactable::colDef(
header = function(value) snakecase::to_title_case(value)))
lifeformobservations <- LifeformsPresence(field.season = year.range)
lifeformobservations %>%
reactable::reactable(
sortable = TRUE,
filterable = TRUE,
compact = TRUE,
striped = TRUE,
bordered = TRUE,
highlight = TRUE,
resizable = TRUE,
defaultColDef = reactable::colDef(
header = function(value) snakecase::to_title_case(value)))
invplants <- InvasivePlants(field.season = year.range)
reactable::reactable(dplyr::select(invplants, -Notes),
defaultColDef = reactable::colDef(minWidth = 50,
header = function(value) snakecase::to_title_case(value)),
details = reactable::colDef(
name = "Notes",
details = function(index) {
note <- invplants$Notes[index]
if (!is.na(note)) {
return(note)
}
}
),
sortable = TRUE,
filterable = TRUE,
compact = TRUE,
striped = TRUE,
bordered = TRUE,
highlight = TRUE,
resizable = TRUE,)
invplantmap <- InvasivePlantsMap(field.season = year.range)
invplantmap
overalldisturbance <- qcOverallDisturbance(field.season = year.range)
overalldisturbance %>%
reactable::reactable(
sortable = TRUE,
filterable = TRUE,
compact = TRUE,
striped = TRUE,
bordered = TRUE,
highlight = TRUE,
resizable = TRUE,
defaultColDef = reactable::colDef(
header = function(value) snakecase::to_title_case(value)))
flowmodnohumanuse <- qcFlowModNoHumanUse(field.season = year.range)
flowmodnohumanuse %>%
reactable::reactable(
sortable = TRUE,
filterable = TRUE,
compact = TRUE,
striped = TRUE,
bordered = TRUE,
highlight = TRUE,
resizable = TRUE,
defaultColDef = reactable::colDef(
header = function(value) snakecase::to_title_case(value)))
flowmoddiscrepancies <- qcFlowModDiscrepancies(field.season = year.range)
flowmoddiscrepancies %>%
reactable::reactable(
sortable = TRUE,
filterable = TRUE,
compact = TRUE,
striped = TRUE,
bordered = TRUE,
highlight = TRUE,
resizable = TRUE,
defaultColDef = reactable::colDef(
header = function(value) snakecase::to_title_case(value)))
flowmodstatus <- FlowModStatus(field.season = year.range)
flowmodstatus %>%
reactable::reactable(
sortable = TRUE,
filterable = TRUE,
compact = TRUE,
striped = TRUE,
bordered = TRUE,
highlight = TRUE,
resizable = TRUE,
defaultColDef = reactable::colDef(
header = function(value) snakecase::to_title_case(value)))
flowmodcount <- FlowModCount(field.season = year.range)
flowmodcount %>%
reactable::reactable(
sortable = TRUE,
filterable = TRUE,
compact = TRUE,
striped = TRUE,
bordered = TRUE,
highlight = TRUE,
resizable = TRUE,
defaultColDef = reactable::colDef(
header = function(value) snakecase::to_title_case(value)))
flowmodplot <- FlowModPlot(field.season = year.range)
if (params$isAccessible == "yes") {
flowmodplot
} else {
ggplotly(flowmodplot)
}
disturbcount <- DisturbanceCount(field.season = year.range)
disturbcount %>%
reactable::reactable(
sortable = TRUE,
filterable = TRUE,
compact = TRUE,
striped = TRUE,
bordered = TRUE,
highlight = TRUE,
resizable = TRUE,
defaultColDef = reactable::colDef(
header = function(value) snakecase::to_title_case(value)))
humanuseobs <- HumanUseObservations(field.season = year.range)
reactable::reactable(dplyr::select(humanuseobs, -Notes),
defaultColDef = reactable::colDef(minWidth = 50,
header = function(value) snakecase::to_title_case(value)),
details = reactable::colDef(
name = "Notes",
details = function(index) {
note <- humanuseobs$Notes[index]
if (!is.na(note)) {
return(note)
}
}
),
sortable = TRUE,
filterable = TRUE,
compact = TRUE,
striped = TRUE,
bordered = TRUE,
highlight = TRUE,
resizable = TRUE)
humanuseplot <- HumanUsePlot(field.season = year.range)
if (params$isAccessible == "yes") {
humanuseplot
} else {
ggplotly(humanuseplot)
}
humanusemap <- HumanUseMap(field.season = year.range)
humanusemap
livestockobs <- LivestockObservations(field.season = year.range)
reactable(dplyr::select(livestockobs, -Notes),
defaultColDef = reactable::colDef(minWidth = 50,
header = function(value) snakecase::to_title_case(value)),
details = reactable::colDef(
name = "Notes",
details = function(index) {
note <- livestockobs$Notes[index]
if (!is.na(note)) {
return(note)
}
}
),
sortable = TRUE,
filterable = TRUE,
compact = TRUE,
striped = TRUE,
bordered = TRUE,
highlight = TRUE,
resizable = TRUE)
livestockplot <- LivestockPlot(field.season = year.range)
if (params$isAccessible == "yes") {
livestockplot
} else {
ggplotly(livestockplot)
}
livestockmap <- LivestockMap(field.season = year.range)
livestockmap
wildlifenotype <- qcWildlifeObservedNoTypes(field.season = year.range)
reactable(dplyr::select(wildlifenotype, -Notes),
defaultColDef = reactable::colDef(minWidth = 50,
header = function(value) snakecase::to_title_case(value)),
details = reactable::colDef(
name = "Notes",
details = function(index) {
note <- wildlifenotype$Notes[index]
if (!is.na(note)) {
return(note)
}
}
),
sortable = TRUE,
filterable = TRUE,
compact = TRUE,
striped = TRUE,
bordered = TRUE,
highlight = TRUE,
resizable = TRUE)
wildlifenoevidence <- qcWildlifeObservedNoEvidence(field.season = year.range)
reactable(dplyr::select(wildlifenoevidence, -Notes),
defaultColDef = reactable::colDef(minWidth = 50,
header = function(value) snakecase::to_title_case(value)),
details = reactable::colDef(
name = "Notes",
details = function(index) {
note <- wildlifenoevidence$Notes[index]
if (!is.na(note)) {
return(note)
}
}
),
sortable = TRUE,
filterable = TRUE,
compact = TRUE,
striped = TRUE,
bordered = TRUE,
highlight = TRUE,
resizable = TRUE)
ungulatesevidence <- UngulatesEvidence(field.season = year.range)
reactable(dplyr::select(ungulatesevidence, -Notes),
defaultColDef = reactable::colDef(minWidth = 50,
header = function(value) snakecase::to_title_case(value)),
details = reactable::colDef(
name = "Notes",
details = function(index) {
note <- ungulatesevidence$Notes[index]
if (!is.na(note)) {
return(note)
}
}
),
sortable = TRUE,
filterable = TRUE,
compact = TRUE,
striped = TRUE,
bordered = TRUE,
highlight = TRUE,
resizable = TRUE)
ungulatesmap <- UngulatesMap(field.season = year.range)
ungulatesmap
sessionInfo()
Sys.time() R version 4.2.0 (2022-04-22 ucrt)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 10 x64 (build 19045)
Matrix products: default
locale:
[1] LC_COLLATE=English_United States.utf8
[2] LC_CTYPE=English_United States.utf8
[3] LC_MONETARY=English_United States.utf8
[4] LC_NUMERIC=C
[5] LC_TIME=English_United States.utf8
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] desertsprings_0.1.0 EMLassemblyline_3.5.5 DT_0.27
[4] tidytext_0.4.1 glue_1.6.2 gridExtra_2.3
[7] slickR_0.6.0 reactable_0.4.3 snakecase_0.11.0
[10] scales_1.2.1 svglite_2.1.1 plotly_4.10.1
[13] leaflet_2.1.2 magrittr_2.0.3 formatR_1.14
[16] forcats_1.0.0 stringr_1.5.0 purrr_1.0.1
[19] readr_2.1.3 tidyr_1.3.0 tibble_3.1.8
[22] ggplot2_3.4.0 tidyverse_1.3.2 remotes_2.4.2
[25] english_1.2-6 kableExtra_1.3.4 EML_2.0.6.1
[28] RODBC_1.3-20 devtools_2.4.5 usethis_2.1.6
[31] here_1.0.1 knitcitations_1.0.12 RefManageR_1.4.0
[34] bibtex_0.5.1 htmltools_0.5.4 rmdformats_1.0.4
[37] yaml_2.3.7 rmdHelpers_1.2 dplyr_1.1.0
[40] texreg_1.38.6 papeR_1.0-5 xtable_1.8-4
[43] car_3.1-1 carData_3.0-5 kimisc_0.4
[46] R.rsp_0.45.0 dataMaid_1.4.1 knitr_1.42
[49] pander_0.6.5 rmarkdown_2.20 markdown_1.5
loaded via a namespace (and not attached):
[1] readxl_1.4.1 uuid_1.1-0 backports_1.4.1
[4] systemfonts_1.0.4 plyr_1.8.8 lazyeval_0.2.2
[7] jqr_1.2.3 crosstalk_1.2.0 SnowballC_0.7.0
[10] digest_0.6.31 gdata_2.18.0.1 fansi_1.0.4
[13] checkmate_2.1.0 memoise_2.0.1 emld_0.5.1
[16] googlesheets4_1.0.1 tzdb_0.3.0 modelr_0.1.10
[19] gmodels_2.18.1.1 vroom_1.6.1 R.utils_2.12.2
[22] timechange_0.2.0 prettyunits_1.1.1 colorspace_2.1-0
[25] rvest_1.0.3 haven_2.5.1 xfun_0.37
[28] callr_3.7.3 crayon_1.5.2 jsonlite_1.8.4
[31] gtable_0.3.1 gargle_1.3.0 webshot_0.5.4
[34] V8_4.2.2 R.cache_0.16.0 pkgbuild_1.4.0
[37] DEoptimR_1.0-11 abind_1.4-5 DBI_1.1.3
[40] miniUI_0.1.1.1 Rcpp_1.0.10 viridisLite_0.4.1
[43] bit_4.0.5 profvis_0.3.7 htmlwidgets_1.6.2
[46] httr_1.4.4 RColorBrewer_1.1-3 ellipsis_0.3.2
[49] farver_2.1.1 urlchecker_1.0.1 pkgconfig_2.0.3
[52] R.methodsS3_1.8.2 sass_0.4.5 dbplyr_2.3.0
[55] utf8_1.2.3 labeling_0.4.2 tidyselect_1.2.0
[58] rlang_1.0.6 later_1.3.0 reactR_0.4.4
[61] munsell_0.5.0 cellranger_1.1.0 tools_4.2.0
[64] cachem_1.0.6 cli_3.6.0 generics_0.1.3
[67] broom_1.0.3 evaluate_0.20 fastmap_1.1.0
[70] bit64_4.0.5 processx_3.8.0 fs_1.6.0
[73] jsonld_2.2 robustbase_0.95-0 mime_0.12
[76] R.oo_1.25.0 xml2_1.3.3 tokenizers_0.3.0
[79] compiler_4.2.0 rstudioapi_0.14 curl_5.0.0
[82] reprex_2.0.2 bslib_0.4.2 stringi_1.7.12
[85] highr_0.10 ps_1.7.2 lattice_0.20-45
[88] Matrix_1.5-3 vctrs_0.5.2 pillar_1.8.1
[91] lifecycle_1.0.3 jquerylib_0.1.4 data.table_1.14.6
[94] httpuv_1.6.8 R6_2.5.1 bookdown_0.32
[97] promises_1.2.0.1 janeaustenr_1.0.0 sessioninfo_1.2.2
[100] MASS_7.3-59 gtools_3.9.4 assertthat_0.2.1
[103] pkgload_1.3.2 rprojroot_2.0.3 withr_2.5.0
[106] hms_1.1.2 grid_4.2.0 googledrive_2.0.0
[109] base64enc_0.1-3 shiny_1.7.4 lubridate_1.9.1
[1] "2023-05-04 16:24:36 PDT"
The National Park Service, Natural Resource Stewardship and Science office in Fort Collins, Colorado, publishes a range of reports that address natural resource topics. These reports are of interest and applicability to a broad audience in the National Park Service and others in natural resource management, including scientists, conservation and environmental constituencies, and the public.
Data Release Reports are created by the National Park Service and provide detailed descriptions of valuable research datasets, including the methods used to collect and process the data, technical analyses to evaluate the quality of those data, and information to guide use of those data. Data Release Reports focus on helping others reuse data, rather than presenting results, testing hypotheses, or presenting new interpretations, methods or in-depth analyses.
All manuscripts in the series receive the appropriate level of peer review to ensure that the information is scientifically credible, technically accurate, appropriately written for the intended audience, and designed and published in a professional manner.
The creation of data sets documented in this report followed peer reviewed methods described or referenced herein. Resultant data sets were reviewed to ensure accuracy, completeness, and consistency with documented data quality standards, as well as for usability and reproducibility.
Views, statements, findings, conclusions, recommendations, and data in this report do not necessarily reflect views and policies of the National Park Service, U.S. Department of the Interior. Mention of trade names or commercial products does not constitute endorsement or recommendation for use by the U.S. Government.
This report is available in digital format from the National Park Service Data Store.